home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / slip / cslip-2.6 / tip / page.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-30  |  9.4 KB  |  483 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] =
  20.     "@(#) $Header: page.c,v 1.8 90/06/30 17:14:27 leres Exp $ (LBL)";
  21. #endif
  22.  
  23. /*
  24.  *    tip/page.c
  25.  *
  26.  *    This file contains code to send alphanumeric pages via
  27.  *    dialup paging services that support "Remote Entry Device
  28.  *    Protocol" (aka "IXO").  These services typically send to
  29.  *    devices like the Motorola PMR-2000 pager.
  30.  *
  31.  *    This module is designed to use the ACK/NAK packet protocol
  32.  *    to ensure the highest likelyhood of correct delivery of the
  33.  *    message.  The packets are checksummed and all messages are
  34.  *    acknowledged by the receiver.
  35.  *
  36.  *    To use this facility, tip must be called with the -p option,
  37.  *    a system name (what system to dial up) and finally a data
  38.  *    string which contains 3 items:  A login code/password, a list
  39.  *    pager id's to receive the message, and the message text.
  40.  *    The three fields are separated by tabs.  The pager id field
  41.  *    is further subdivided into a list of pager ids by commas.
  42.  *
  43.  *    For example:
  44.  *    tip -p metro "12345678\t20001,20002\tPlease call the office."
  45.  *
  46.  *    Would call the system called "metro" as listed in /etc/remote
  47.  *    and login with the ID 12345678.  The message "Please call
  48.  *    the office." would be sent to pagers 20001 and 20002.
  49.  *
  50.  *    This code has been tested only on the Metromedia Paging Services
  51.  *    system around New York City, though it should work on other
  52.  *    similiar systems.
  53.  */
  54.  
  55. #include <stdio.h>
  56. #include <ctype.h>
  57. #include <signal.h>
  58. #include <sys/time.h>
  59. #include "tip.h"
  60.  
  61. #define STX    002    /* ^B */
  62. #define    ETX    003    /* ^C */
  63. #define    EOT    004    /* ^D */
  64. #define    ACK    006    /* ^F */
  65. #define    NAK    025    /* ^U */
  66. #define    ETB    027    /* ^W */
  67. #define    ESC    033    /* ^[ */
  68. #define    RS    036    /* ^^ */
  69.  
  70. #define WRITE_DELAY 40        /* ms between each character written to modem */
  71.  
  72. #ifdef notdef
  73. extern jmp_buf    jmpbuf;
  74. #endif
  75.  
  76. extern char *strchr();
  77. extern int recvtimeout();
  78.  
  79. char    inbuf[270];
  80. #ifdef notdef
  81. char    mbuf[32];
  82. #endif
  83. char    packet[270];
  84.  
  85. static char *addstr();
  86.  
  87. static int pgrecv();
  88. static int pgsend();
  89. static int lread();
  90. static int lputc();
  91. static void errputs();
  92. static void errputc();
  93.  
  94. sendpage(data)
  95. char *data;
  96. {
  97.     int ret = 1;
  98.     int trys, i;
  99.     char *cp, *pager, *message;
  100.     char *cp2;
  101.     char buf[65 + 2];        /* 65 char max sized msg + CR + EOS */
  102.  
  103.     if (boolean(value(VERBOSE)))
  104.         vflag++;
  105. #ifdef notdef
  106. #endif
  107.     if (vflag)
  108.         fputs("[Connected]\n", stderr);
  109.  
  110.     cp = data;
  111.     if (pager = strchr(data, '\t')) {
  112.         *pager = 0;
  113.         pager++;
  114.     } else {
  115.         fprintf(stderr, "Bad paging data: '%s'\n", data);
  116.         return(1);
  117.     }
  118.  
  119.     trys = 0;
  120.     do {
  121.         if (trys++ > 3) {
  122.             fprintf(stderr, "ID= retries failed\n");
  123.             goto done;
  124.         }
  125.         if (pgsend("\r"))
  126.             return(1);
  127.     } while (pgrecv("ID=", 5) < 3);
  128.  
  129.     trys = 0;
  130. login_again:
  131.  
  132.     (void)sprintf(buf, "\033%s\r", cp);
  133.     if (pgsend(buf))
  134.         return(1);
  135.  
  136.     /* Check what's echoed back */
  137.     cp2 = buf;
  138.     ++cp2;        /* step over escape */
  139.     strcat(cp2, "\n\r");
  140.     if (pgrecv(cp2, 10) <= 0) {
  141.         if (trys++ < 4)
  142.             goto login_again;
  143.         else
  144.             goto done;
  145.     }
  146.  
  147.     /* Wait for ACK, NAK, EOT or Ready(?) */
  148.     if (pgrecv("\r", 10) <= 0) {
  149.         fprintf(stderr, "login timeout\n");
  150.         goto done;
  151.     }
  152.  
  153.     switch(inbuf[0]) {
  154.  
  155.     default:    if (trys++ < 4) goto login_again; else goto done;
  156.     case ACK:    break;
  157.     case NAK:    if (trys++ < 4) goto login_again; else goto done;
  158.     case RS:    fprintf(stderr, "login got RS\n"); goto done;
  159.     case ESC:
  160.         switch(inbuf[1]) {
  161.         case EOT:    goto done;
  162.         case '[':    if(inbuf[2] == 'p') break;
  163.         default:    fprintf(stderr, "got unknown ESC code\n");
  164.                 goto login_again;
  165.         }
  166.     }
  167.     pgrecv("\r", 10);    /* Swallow version greeting */
  168.     pgrecv("\r", 10);    /* Swallow Go Ahead <ESC>[p */
  169.  
  170.     if (message = strchr(pager, '\t')) {
  171.         *message = 0;
  172.         message++;
  173.     } else
  174.         message = "[Message not specified]";
  175. next_pager:
  176.     if (cp = strchr(pager, ','))
  177.         *cp++ = '\0';
  178.     buildpkt(pager, message);
  179.  
  180.     trys = 0;
  181. resend:
  182.     if (pgsend(packet))
  183.         return(1);
  184.  
  185.     pgrecv("\r", 10);    /* Swallow page id echo */
  186.  
  187. #ifdef notdef
  188.     /* ??? */
  189.     pgrecv("^C\r\n", 10);    /* ^C\r\n */
  190. #endif
  191.  
  192.     /* Wait for ACK, NAK, EOT or Ready(?) */
  193. again:
  194.     if ((i = pgrecv("\r", 10)) <= 0) {
  195.         fprintf(stderr, "page send no reply\n");
  196.         goto done;
  197.     }
  198.     switch (inbuf[0]) {
  199.  
  200.     default:
  201.         fprintf(stderr, "page send reply error\n");
  202.         goto done;
  203.  
  204.     case ACK:    
  205.         ret = 0;
  206.         pgrecv("\r", 10);    /* Swallow page placed message */
  207.         pgrecv("\r", 10);    /* Swallow thank you */
  208.         goto again;
  209.         /* goto sent; */
  210.  
  211.     case NAK:
  212.         if (trys++ < 4)
  213.             goto resend;
  214.         else
  215.             goto done;
  216.     case RS:
  217.         fprintf(stderr, "page send got RS\n");
  218.         goto done;
  219.  
  220.     case ESC:
  221.         switch (inbuf[1]) {
  222.  
  223.         case EOT:
  224.             goto done;
  225.  
  226.         case '[':
  227.             if(inbuf[2] == 'p') {
  228.                 ret = 1;
  229.                 goto sent;
  230.             }
  231.             /* Fall through */
  232.  
  233.         default:
  234.             fprintf(stderr, "got unknown ESC code (2) \"");
  235.             errputs(inbuf);
  236.             fprintf(stderr, "\"\n");
  237.             goto done;
  238.         }
  239.     }
  240. sent:
  241.     if (cp) {
  242.         pager = cp;
  243.         goto next_pager;
  244.     }
  245.  
  246. done:
  247.     /* Logout: EOT CR */
  248.     if (pgsend("\004\r"))
  249.         return(ret);
  250.     pgrecv("\r", 3);
  251.     fputs(ret ? "[Error in delivery]\n" : inbuf, stderr);
  252.     pgrecv("\r", 3);
  253.     return(ret);
  254. }
  255.  
  256. static int
  257. pgsend(cp)
  258.     register char *cp;
  259. {
  260.     register char c;
  261.     struct timeval t;
  262.  
  263.     if (debug)
  264.         fputs("-> \"", stderr);
  265.     t.tv_sec = 0;
  266.     t.tv_usec = WRITE_DELAY * 1000000;
  267.     while (*cp) {
  268.         c = *cp++;
  269.         if (lputc(c) != 1)
  270.             return(-1);
  271.         if (debug)
  272.             errputc(c);
  273.         (void) select(32, 0, 0, 0, &t);
  274.     }
  275.     if (debug)
  276.         fputs("\"\n", stderr);
  277.     return(0);
  278. }
  279.  
  280. static int
  281. pgrecv(want, secs)
  282.     char *want;
  283.     int secs;
  284. {
  285.     register int i, j, n, size;
  286. int cnt;
  287. char *inbufp = inbuf;
  288. char buf[sizeof(inbuf)];
  289.     char *endstr = "\"\n";
  290.     cnt = 0;
  291.     
  292.     size = strlen(want);
  293.     if (size >= sizeof(buf)) {
  294.         (void)fprintf(stderr, "pgrecv: size too big  (%d >= %d)",
  295.             size, sizeof(buf));
  296.         return(-1);
  297.     }
  298.     if (debug) {
  299.         fputs("<? \"", stderr);
  300.         errputs(want);
  301.         fputs("\"\n<- \"", stderr);
  302.     }
  303.     for (i = 0; i < size; ) {
  304.         /* Read as much as we can, handle timeout and errors */
  305.         if ((n = lread(FD, &buf[i], size - i, (u_int)secs)) < 0) {
  306.             if (debug)
  307.                 fputs(endstr, stderr);
  308.             (void)fprintf(stderr, "pgrecv: lread(1): %s\n",
  309.                 strerror(errno));
  310.             return(-1);
  311.         } else if (n == 0) {
  312.             if (debug)
  313.                 fputs(endstr, stderr);
  314. #ifdef notdef
  315.             fprintf(stderr, "pgrecv: timeout (1)");
  316. #endif
  317.             return(0);
  318.         }
  319.         cnt += n;
  320.  
  321.         /* Gag, ANYP is all it's cracked up to be */
  322.         for (j = i; j < i + n; ++j) {
  323.             buf[j] &= 0177;
  324. *inbufp++ = buf[j];
  325.         }
  326.         if (debug)
  327.             for (j = i; j < i + n; ++j)
  328.                 errputc(buf[j]);
  329.         i += n;
  330.         buf[i] = '\0';
  331. *inbufp = '\0';
  332.     }
  333.     i = size - 1;
  334.     while (strncmp(buf, want, size)) {
  335.         bcopy(buf + 1, buf, size);
  336.         if ((n = lread(FD, &buf[i], 1, (u_int)secs)) < 0) {
  337.             if (debug)
  338.                 fputs(endstr, stderr);
  339.             (void)fprintf(stderr, "pgrecv: lread(2): %s\n",
  340.                 strerror(errno));
  341.             return(-1);
  342.         } else if (n == 0) {
  343.             if (debug)
  344.                 fputs(endstr, stderr);
  345. #ifdef notdef
  346.             fprintf(stderr, "pgrecv: timeout (2)");
  347. #endif
  348.             return(0);
  349.         }
  350.         cnt += n;
  351.         buf[i] &= 0177;
  352. *inbufp++ = buf[i];
  353.         if (debug)
  354.             errputc(buf[i]);
  355.     }
  356.     if (debug)
  357.         fputs(endstr, stderr);
  358.  
  359. *inbufp++ = '\0';
  360. #ifdef notdef
  361. fprintf(stderr, "\rpgrecv: cnt is %d, size is %d, inbuf '", cnt, size);
  362. errputs(inbuf);
  363. fprintf(stderr, "'\n");
  364. #endif
  365.     return(cnt);
  366. }
  367.  
  368.  
  369. buildpkt(pager, message)
  370. char *pager, *message;
  371. {
  372.     char    *cp = &packet[0];
  373.     int    sum;
  374.  
  375.     *cp++ = STX;
  376.     sum = STX;
  377.  
  378.     cp = addstr(pager, &sum, cp);
  379.     cp = addstr(message, &sum, cp);
  380.  
  381.     *cp++ = ETX;
  382.     sum += ETX;
  383.     *cp++ = '0' + ((sum>>8)&0xf);
  384.     *cp++ = '0' + ((sum>>4)&0xf);
  385.     *cp++ = '0' + (sum&0xf);
  386.     *cp++ = '\r';
  387.     *cp = '\0';
  388. }
  389.  
  390. static char *
  391. addstr(s, sump, cp)
  392. char *s, *cp;
  393. int *sump;
  394. {
  395.     char c;
  396.     int sum = *sump;
  397.  
  398.     while(c = *s++) {
  399.         *cp = (isprint(c) ? c : '?');
  400.         sum += *cp;
  401.         cp++;
  402.     }
  403.     *cp++ = '\r';
  404.     sum += '\r';
  405.  
  406.     *sump = sum;
  407.     return(cp);
  408. }
  409.  
  410. static int
  411. lread(f, buf, len, secs)
  412.     int f;
  413.     char *buf;
  414.     int len;
  415.     u_int secs;
  416. {
  417.     register int n;
  418.     struct timeval t;
  419.     int readfds;
  420.  
  421.     t.tv_sec = secs;
  422.     t.tv_usec = 0;
  423.     readfds = 1 << FD;
  424.     if ((n = select(f + 1, &readfds, 0, 0, &t)) <= 0)
  425.         return(n);
  426.     return(read(f, buf, len));
  427. }
  428.  
  429. static int
  430. lputc(c)
  431.     char c;
  432. {
  433.     struct timeval t;
  434.  
  435.     if (write(FD, &c, 1) != 1)
  436.         return(-1);
  437.     t.tv_sec = 0;
  438.     t.tv_usec = WRITE_DELAY * 1000000;
  439.     (void) select(32, 0, 0, 0, &t);
  440.     return(1);
  441. }
  442.  
  443. static void
  444. errputs(s)
  445.     register char *s;
  446. {
  447.     while (*s)
  448.         errputc(*s++);
  449. }
  450.  
  451. static void
  452. errputc(c)
  453.     char c;
  454. {
  455.     if (c & ~ 0177) {
  456.         putc('M', stderr);
  457.         putc('-', stderr);
  458.         c &= 0177;
  459.     }
  460.     if (c < 0x20 || c == 0177) {
  461.         if (c == '\b') {
  462.             putc('\\', stderr);
  463.             putc('b', stderr);
  464.         } else if (c == '\f') {
  465.             putc('\\', stderr);
  466.             putc('f', stderr);
  467.         } else if (c == '\n') {
  468.             putc('\\', stderr);
  469.             putc('n', stderr);
  470.         } else if (c == '\r') {
  471.             putc('\\', stderr);
  472.             putc('r', stderr);
  473.         } else if (c == '\t') {
  474.             putc('\\', stderr);
  475.             putc('t', stderr);
  476.         } else {
  477.             putc('^', stderr);
  478.             putc(c ^ 0x40, stderr);    /* DEL to ?, others to alpha */
  479.         }
  480.     } else
  481.         putc(c, stderr);
  482. }
  483.